package com.xbongbong.saas.model.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.ScoreConditionEnum;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.pro.domain.dao.ScoreRangeDao;
import com.xbongbong.pro.domain.entity.ScoreRangeConditionEntity;
import com.xbongbong.pro.domain.entity.ScoreRangeEntity;
import com.xbongbong.pro.enums.errorcodes.MirrorErrorCodeEnum;
import com.xbongbong.pro.score.pojo.dto.ScoreRangeDetailDTO;
import com.xbongbong.pro.score.pojo.vo.ScoreRangeDetailVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.enums.ScoreShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.model.ScoreRangeModel;
import com.xbongbong.saas.model.ScoreRuleModel;
import com.xbongbong.saas.service.impl.ScoreRangeConditionServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @description:  评分规则
 * @Author: chunyang.qin
 * @date: 2020-11-27 17:37
 * @since v1.0
 */
@Service("scoreRangeModel")
public class ScoreRangeModelImpl implements ScoreRangeModel {

    private static final Logger LOG = LoggerFactory.getLogger(ScoreRangeModelImpl.class);

    @Resource
    private ScoreRangeDao scoreRangeDao;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private ScoreRuleModel scoreRuleModel;
    @Resource
    private ScoreRangeConditionServiceImpl scoreRangeConditionService;

    @Override
    public Integer insert(ScoreRangeEntity entity) throws XbbException {
        long now = DateUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        entity.setDel(0);
        return scoreRangeDao.insert(entity);
    }

    @Override
    public Integer update(ScoreRangeEntity entity) throws XbbException {
        long now = DateUtil.getInt();
        entity.setUpdateTime(now);
        return scoreRangeDao.update(entity);
    }

    @Override
    public List<ScoreRangeEntity> findEntitys(Map<String, Object> param) {
        return scoreRangeDao.findEntitys(param);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return scoreRangeDao.getEntitysCount(param);
    }

    @Override
    public List findEntitysWithoutSub(Map<String, Object> param) {
        return null;
    }

    @Override
    public ScoreRangeEntity getByKey(Long key, String corpid) {
        return scoreRangeDao.getByKey(key,corpid);
    }

    @Override
    public ScoreRangeEntity getByFormId(Long formId, String corpid) {
        return scoreRangeDao.getByFormId(formId,corpid);
    }

    @Override
    public Integer deleteByKey(Long key, String corpid) {
        return scoreRangeDao.deleteByKey(key,corpid);
    }

    @Override
    public ScoreRangeDetailVO getScoreRange(ScoreRangeDetailDTO scoreRangeDetailDTO) throws XbbException {
        ScoreRangeDetailVO scoreRangeDetailVO = new ScoreRangeDetailVO();
        List<ScoreRangeConditionEntity> scoreRangeList = new ArrayList<>();
        scoreRangeDetailVO.setScoreShowType(ScoreShowTypeEnum.DEFAULT.getCode());

        Long formId = scoreRangeDetailDTO.getFormId();
        String corpid = scoreRangeDetailDTO.getCorpid();
        ScoreRangeEntity scoreRangeEntity = getByFormId(formId, corpid);
        //如果在score_range 表中找到数据，说明这条规则是设置过自定义范围展示的,enable 值为1 表示的是这个自定义范围展示时启用，为0 表示是不启用，不启用就展示分值
        if (Objects.nonNull(scoreRangeEntity)) {
            String data = scoreRangeEntity.getData();
            Long dateId = scoreRangeEntity.getId();
            scoreRangeDetailVO.setScoreShowType(scoreRangeEntity.getEnable());
            if (Objects.nonNull(dateId)) {
                scoreRangeDetailVO.setDataId(dateId);
            }
            if (Objects.nonNull(data)) {
                scoreRangeList = JSONArray.parseArray(data, ScoreRangeConditionEntity.class);
            }
        }
        scoreRangeDetailVO.setScoreRangeList(scoreRangeList);
        return scoreRangeDetailVO;
    }

    @Override
    /**
     * 获取评分展示的值
     * @return 评分的展示方式，没有命中的话展示 “-”。
     * Double score, ScoreRangeDetailVO scoreRangeDetailVO
     * PaasFormDataEntityExt
     */
    public String getScoreShowValue(Integer businessType , PaasFormDataEntityExt paasFormDataEntityExt) throws XbbException {
        try{
            Long formId = paasFormDataEntityExt.getFormId();
            String corpid = paasFormDataEntityExt.getCorpid();
            //以下情况不展示评分 (1)套餐是标准版（2）该表单下没有启用的评分规则(应用不开启的话，是无法调这边方法的，所以不需要判断应用是否开启)
            if(packageHelp.isStandardWithFeeType(corpid) || (!scoreRuleModel.haveEnabledScoreRule(corpid,formId))){
                return null;
            }
            String scoreStringValue = null;
            Double score = null;
            //检查业务类型，客户,线索才支持(注意：返回null 和返回 -- 是有区别的，会影响到移动端详情页的展示)
            if(!XbbRefTypeEnum.checkScoreBusinessType(businessType)){
                LOG.error("业务类型错误，评分展示返回null值,入参businessType-{}-", JSON.toJSONString(businessType));
                return null;
            }
            JSONObject data = paasFormDataEntityExt.getData();
            if(Objects.isNull(corpid) || Objects.isNull(formId) || Objects.isNull(data)){
                return "--";
            }
            XbbRefTypeEnum xbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            Object scoreObject = null;
            switch (xbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    scoreObject = data.get(CustomerManagementEnum.SCORE.getAttr());
                    break;
                case CLUE:
                    scoreObject = data.get(ClueEnum.SCORE.getAttr());
                    break;
                default:
                    break;
            }
            //未参与评分的老数据，num_61的值是空的，不做处理.也有可能是空串，不知道哪里搞出来的
            if(Objects.isNull(scoreObject) || String.valueOf(scoreObject).length() == 0){
                return "--";
            }
            ScoreRangeDetailVO scoreRangeDetailVO = getScoreRange(new ScoreRangeDetailDTO(corpid, formId));
            //展示方式为 分值的话，直接返回分值
            return getScoreShowValue(scoreRangeDetailVO, scoreObject);
        }catch (Exception e){
            LOG.error("getScoreShowValue 发送异常");
        }
        return "--";
    }

    /**
     * 等于空表示没有命中
     * @param score
     * @param scoreRangeEntity
     * @return
     * @throws XbbException
     */
    private String getShowValue(Double score,ScoreRangeConditionEntity scoreRangeEntity) throws XbbException {
        if(Objects.nonNull(scoreRangeEntity)){
            ScoreConditionEnum scoreConditionEnum = ScoreConditionEnum.getConditionEnum(scoreRangeEntity.getSymbol());
            switch (scoreConditionEnum){
                case EQUAL:
                    return scoreRangeConditionService.equal(score,scoreRangeEntity);
                case NOEQUAL:
                    return scoreRangeConditionService.noequal(score,scoreRangeEntity);
                case GREATEREQUAL:
                    return scoreRangeConditionService.greaterequal(score,scoreRangeEntity);
                case GREATERTHAN:
                    return scoreRangeConditionService.greatethan(score,scoreRangeEntity);
                case LESSEQUAL:
                    return scoreRangeConditionService.lessequal(score,scoreRangeEntity);
                case LESSTHAN:
                    return scoreRangeConditionService.lessthan(score,scoreRangeEntity);
                case RANGE:
                    return scoreRangeConditionService.range(score,scoreRangeEntity);
                default:
                    throw new XbbException(MirrorErrorCodeEnum.API_ERROR_403006, MirrorErrorCodeEnum.API_ERROR_403006.getMsg());
            }
        }
        return null;
    }

    /**
     * 判断该表表单的评分展示方式，是否是"区间"；
     * true 代表是区间展示;
     * @return
     */
    @Override
    public Boolean isRangWithScoreShowType(String corpid , Long formId) throws XbbException {
        ScoreRangeDetailVO scoreRange = getScoreRange(new ScoreRangeDetailDTO(corpid, formId));
        return Objects.equals(scoreRange.getScoreShowType(),ScoreShowTypeEnum.RANGE.getCode());
    }

    @Override
    public void scoreCondition(String corpid, List<ConditionsEntityExt> conditions, Long formId) throws XbbException {
        // 判断客户或者线索的评分字段，可抽离
        if (!packageHelp.isStandardWithFeeType(corpid) && CollectionsUtil.isNotEmpty(conditions)) {
            for (int i = conditions.size() - 1; i >= 0; i--) {
                ConditionsEntityExt screenCondition = conditions.get(i);
                String attr = screenCondition.getAttr();
                List<Object> values = screenCondition.getValue();
                //展示方式是按照区间展示时
                if(isRangWithScoreShowType(corpid,formId) && CollectionsUtil.isNotEmpty(values)){
                    //筛选的字段是评分业务的字段
                    if(Objects.equals(attr, CustomerManagementEnum.SCORE.getAttr())){
                        //查询评分展示区间。
                        ScoreRangeDetailVO scoreRange = getScoreRange(new ScoreRangeDetailDTO(corpid, formId));                        List<ScoreRangeConditionEntity> scoreRangeList = scoreRange.getScoreRangeList();
                        //评分区间的value  就是 scoreRangeList 的index
                        if(CollectionsUtil.isNotEmpty(scoreRangeList)){
                            ScoreRangeConditionEntity scoreRangeCondition = scoreRangeList.get((Integer)(values.get(0)));
                            screenCondition.setSymbol(scoreRangeCondition.getSymbol());
                            screenCondition.setValue(scoreRangeCondition.getValue());
                        }

                    }
                }
            }
        }
    }

    @Override
    public void getScoreShowValueByList(Integer businessType, String corpid, Long formId, List<PaasFormDataEntityExt> dataList) throws XbbException {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }
        //以下情况不展示评分 (1)套餐是标准版（2）该表单下没有启用的评分规则(应用不开启的话，是无法调这边方法的，所以不需要判断应用是否开启)
        if(packageHelp.isStandardWithFeeType(corpid) || (!scoreRuleModel.haveEnabledScoreRule(corpid,formId))){
            return;
        }
        //检查业务类型，客户,线索才支持(注意：返回null 和返回 -- 是有区别的，会影响到移动端详情页的展示)
        if(!XbbRefTypeEnum.checkScoreBusinessType(businessType)){
            LOG.error("业务类型错误，评分展示返回null值,入参businessType-{}-", JSON.toJSONString(businessType));
            return;
        }
        ScoreRangeDetailVO scoreRangeDetailVO = getScoreRange(new ScoreRangeDetailDTO(corpid, formId));
        Map<Integer, String> fieldList = new HashMap<>(BasicConstant.TWO);
        fieldList.put(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), CustomerManagementEnum.SCORE.getAttr());
        fieldList.put(XbbRefTypeEnum.CLUE.getCode(), ClueEnum.SCORE.getAttr());
        String attr = fieldList.get(businessType);
        dataList.forEach(item->{
            JSONObject data = item.getData();
            if (Objects.isNull(data)) {
                return;
            }
            Object scoreObject = data.get(attr);
            String showValue = getScoreShowValue(scoreRangeDetailVO, scoreObject);
            data.put(attr, showValue);
        });
    }

    private String getScoreShowValue(ScoreRangeDetailVO scoreRangeDetailVO, Object scoreObject) {
        try {
            //未参与评分的老数据，num_61的值是空的，不做处理.也有可能是空串，不知道哪里搞出来的
            if(Objects.isNull(scoreObject) || String.valueOf(scoreObject).length() == 0){
                return "--";
            }
            //数据分值 data 拿出来是值兼容integer,这边再多处理一下
            Double score = ((Number) scoreObject).doubleValue();
            //分数值 去除多余的 0,去除科学计数法后，toString的值
            String scoreStringValue = BigDecimal.valueOf(score).stripTrailingZeros().toPlainString();
            //展示方式为 分值的话，直接返回分值
            if (scoreRangeDetailVO.getScoreShowType().equals(ScoreShowTypeEnum.DEFAULT.getCode())) {
                return scoreStringValue;
            }
            //评分展示方式是区间，但是评分展示规则为空时，展示--
            List<ScoreRangeConditionEntity> scoreRangeList = scoreRangeDetailVO.getScoreRangeList();
            if(CollectionUtils.isEmpty(scoreRangeList)){
                return "--";
            }
            //命中第一个直接返回
            for(ScoreRangeConditionEntity scoreRangeEntity : scoreRangeList){
                String showValue = getShowValue(score, scoreRangeEntity);
                if(Objects.nonNull(showValue)){
                    return showValue;
                }
            }
        } catch (Exception e) {
            LOG.error("com.xbongbong.saas.model.impl.ScoreRangeModelImpl.getScoreShowValue error ", e);
        }
        //全部没有命中，返回“-”
        return "--";
    }
}
